package com.example.webrtcrooma.webrtc.socket;



import android.util.Log;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.example.webrtcrooma.ChatRoomActivity;
import com.example.webrtcrooma.MainActivity;
import com.example.webrtcrooma.connection.PeerConnectionManager;


import org.java_websocket.client.WebSocketClient;
import org.java_websocket.handshake.ServerHandshake;
import org.json.JSONArray;
import org.json.JSONObject;
import org.webrtc.DataChannel;
import org.webrtc.IceCandidate;
import org.webrtc.MediaStream;
import org.webrtc.PeerConnection;
import org.webrtc.RtpReceiver;

import java.net.URI;
import java.net.URISyntaxException;
import java.security.SecureRandom;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;

import static android.content.ContentValues.TAG;

public class WebRtcSocketManager {
    PeerConnectionManager peerConnectionManager;
    private MainActivity activity;//连接房间服务器
    private WebSocketClient webSocketClient;
    public WebRtcSocketManager(MainActivity activity, PeerConnectionManager peerConnectionManager){
        this.activity = activity;
        this.peerConnectionManager = peerConnectionManager;
    }
//连接方法  wss Web Socket Secure WebSocket 的加密版本
    public void connect(String wss){
        URI  uri = null;
        try {
            uri = new URI(wss);
        } catch (URISyntaxException e) {
            e.printStackTrace();
        }
        webSocketClient = new WebSocketClient(uri){

            @Override
            public void onOpen(ServerHandshake handshakedata) {
                ChatRoomActivity.openActivity(activity);
            }

            @Override
            public void onMessage(String message) {
                Map map = JSON.parseObject(message, Map.class);
                String eventName = (String)map.get("eventName");
                if(eventName.equals("_peers")){
                    handlerJoinRoom(map);
                }
                if (eventName.equals("_new_peer")) {
                    handleRemoteInRoom(map);
                }
                if (eventName.equals("_answer")){
                    handlerAnswer(map);
                }
                if (eventName.equals("_ice_candidate")){
                    handlerRemoteCandidate(map);
                }
                if (eventName.equals("_new_peer")) {
                    handleRemoteInRoom(map);
                }
                if (eventName.equals("_remove_peer")) {
                    handleRemoteOutRoom(map);
                }
            }

            @Override
            public void onClose(int code, String reason, boolean remote) {

            }

            @Override
            public void onError(Exception ex) {

            }
        };
        if (wss.startsWith("wss")){
            try {
                SSLContext sslContext =SSLContext.getInstance("TSL");
                sslContext.init(null,new TrustManager[]{new TrustManagerTest()},new SecureRandom());
                SSLSocketFactory sslSocketFactory = null;
                if (sslContext != null){
                    sslSocketFactory = sslContext.getSocketFactory();
                }
                if(sslSocketFactory != null){
                    webSocketClient.setSocketFactory(sslSocketFactory);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        webSocketClient.connect();
    }

    private void handlerRemoteCandidate(Map map) {

        Log.i("tuch", "JavaWebSocket  6   handleRemoteCandidate: ");
        Map data = (Map) map.get("data");
        String socketId;
        if (data != null) {
            socketId = (String) data.get("socketId");
            String sdpMid = (String) data.get("id");
            sdpMid = (null == sdpMid) ? "video" : sdpMid;
            int sdpMLineIndex = (int) Double.parseDouble(String.valueOf(data.get("label")));
            String candidate = (String) data.get("candidate");
            IceCandidate iceCandidate = new IceCandidate(sdpMid, sdpMLineIndex, candidate);
            peerConnectionManager.onRemoteIceCandidate(socketId, iceCandidate);
        }


    }


    private void handlerAnswer(Map map) {
        Map data = (Map)map.get("data");
        Map sdpDic;
        if(data != null){
            sdpDic = (Map)data.get("sdp");
            String socketId = (String) data.get("socketId");
            String sdp = (String) sdpDic.get("sdp");
            peerConnectionManager.onReceiverAnswer(socketId, sdp);
        }
    }
    // 有人离开了房间
    private void handleRemoteOutRoom(Map map) {
        Log.i("tuch", "handleRemoteOutRoom: ");
        Map data = (Map) map.get("data");
        String socketId;
        if (data != null) {
            socketId = (String) data.get("socketId");
            peerConnectionManager.onRemoteOutRoom(socketId);
        }

    }

    public void joinRoom(String roomId){
        Map<String,Object> map = new HashMap<>();
        map.put("EventName","__join");
        Map<String,Object> childMap = new HashMap<>();
        childMap.put("room",roomId);
        map.put("data",childMap);
        JSONObject jsonObject = new JSONObject(map);
        final  String jsonString = jsonObject.toString();
        Log.e("send",jsonString);
        webSocketClient.send(jsonString);
    }

    public void handlerJoinRoom(Map map){
        Map data = (Map) map.get("data");
        JSONArray arr;
        if(data != null){
            arr =  (JSONArray) map.get("connection");
            String js = com.alibaba.fastjson.JSONObject.toJSONString(arr, SerializerFeature.WriteClassName);
            ArrayList<String> connections = (ArrayList<String>) com.alibaba.fastjson.JSONObject.parseArray(js, String.class);
            String myId = (String) data.get("you");
            peerConnectionManager.joinRoom(this, connections, true, myId);
        }

    }

    // 自己已经在房间，有人进来
    private void handleRemoteInRoom(Map map) {
        Log.i("tuch", "     handleRemoteInRoom: ");
        Map data = (Map) map.get("data");
        String socketId;
        if (data != null) {
            socketId = (String) data.get("socketId");
            peerConnectionManager.onRemoteJoinToRoom(socketId);
        }

    }

    public void sendOffer(String socketId, String sdp) {
        HashMap<String, Object> childMap1 = new HashMap();
        childMap1.put("type", "offer");
        childMap1.put("sdp", sdp);

        HashMap<String, Object> childMap2 = new HashMap();
        childMap2.put("socketId", socketId);
        childMap2.put("sdp", childMap1);

        HashMap<String, Object> map = new HashMap();
        map.put("eventName", "__offer");
        map.put("data", childMap2);

        com.alibaba.fastjson.JSONObject object = new com.alibaba.fastjson.JSONObject(map);
        String jsonString = object.toString();
        Log.d(TAG, "send-->" + jsonString);
        webSocketClient.send(jsonString);

    }
    public void sendIceCandidate(String socketId, IceCandidate iceCandidate) {
        HashMap<String, Object> childMap = new HashMap();
        childMap.put("id", iceCandidate.sdpMid);
        childMap.put("label", iceCandidate.sdpMLineIndex);
        childMap.put("candidate", iceCandidate.sdp);
        childMap.put("socketId", socketId);
        HashMap<String, Object> map = new HashMap();
        map.put("eventName", "__ice_candidate");
        map.put("data", childMap);
        com.alibaba.fastjson.JSONObject object = new com.alibaba.fastjson.JSONObject(map);
        String jsonString = object.toString();
        Log.d(TAG, "send-->" + jsonString);
        webSocketClient.send(jsonString);
    }

    private class TrustManagerTest implements X509TrustManager {
        @Override
        public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {

        }

        @Override
        public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {

        }

        @Override
        public X509Certificate[] getAcceptedIssuers() {
            return new X509Certificate[0];
        }
    }

}
